package com.fz.service.member.impl;


import com.fz.common.Global;
import com.fz.common.ResponseEntity;
import com.fz.common.ResultCode;
import com.fz.dto.client.login.WxAuthDto;
import com.fz.entity.member.Member;
import com.fz.security.AuthExceptionDto;
import com.fz.security.config.SecurityProperties;
import com.fz.security.filter.BhAuthenticationFilter;
import com.fz.security.utils.JwtTokenUtils;
import com.fz.security.utils.SecurityUtils;
import com.fz.service.member.LoginService;
import com.fz.utils.*;
import com.fz.vo.client.login.ClientLoginVo;
import com.fz.vo.client.login.MemberVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Service
@SuppressWarnings("unchecked")
public class LoginServiceImpl implements LoginService {

    protected final Logger logger = LoggerFactory.getLogger(LoginServiceImpl.class.getSimpleName());
    @Resource
    private BhAuthenticationFilter filter;
    @Resource
    private RedisUtil redisUtil;
    @Autowired
    private JwtTokenUtils jwtTokenUtils;
    @Autowired
    public SecurityProperties securityProperties;

    //--- 小程序获取unionid 接口配置参数
//    public static String appid;
//    @Value("${wechat.applet.appid}")
//    public void setAppid(String appid) {
//        LoginServiceImpl.appid = appid;
//    }
//
//    public static String secret;
//    @Value("${wechat.applet.secret}")
//    public void setSecret(String secret) {
//        LoginServiceImpl.secret = secret;
//    }
//
//    public static String grantType;
//    @Value("${wechat.applet.grantType}")
//    public void setGrantType(String grantType) {
//        LoginServiceImpl.grantType = grantType;
//    }
//
//    public static String url;
//    @Value("${wechat.applet.url}")
//    public void setUrl(String url) {
//        LoginServiceImpl.url = url;
//    }
    //--- 小程序获取unionid 接口配置参数

    /**
     * @方法描述: 手机号验证码登录/注册
     * @参数: [login, request, response]
     * @返回值: com.fz.common.ResponseEntity
     * @创建人: I am God
     * @创建时间:: 2021/2/24
     */
    public ResponseEntity loginMc(String mobilePhone,String code, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Authentication auth ;
        try {
            auth = filter.attemptAuthenticationByMc(mobilePhone,code, request, response);
        } catch (BadCredentialsException e) {
            AuthExceptionDto dto = JacksonUtils.string2Obj(e.getMessage(),AuthExceptionDto.class);;
            return ResponseEntity.build(dto.getCode(),dto.getMessage());
        }
        return loginSuccess(auth);
    }

    /**
     * @方法描述: 手机号密码登录与注册
     * @参数: 
     * @返回值: 
     * @创建人: I am God
     * @创建时间:: 2021/2/26
     */
    public ResponseEntity loginByMp(String mobilePhone,String password,HttpServletRequest request, HttpServletResponse response) throws Exception{
        Authentication auth ;
        try {
            auth = filter.attemptAuthenticationByMp(mobilePhone,password, request, response);
        } catch (BadCredentialsException e) {
            AuthExceptionDto dto = JacksonUtils.string2Obj(e.getMessage(),AuthExceptionDto.class);;
            return ResponseEntity.build(dto.getCode(),dto.getMessage());
        }
        return loginSuccess(auth);
    }

    /**
     * @方法描述: 微信授权登录
     * @参数:
     * @返回值:
     * @创建人: I am God
     * @创建时间:: 2021/2/26
     */
    public ResponseEntity loginByWechat(WxAuthDto wxAuthDto, HttpServletRequest request, HttpServletResponse response) throws Exception{
        Authentication auth ;
        try {
            auth = filter.attemptAuthenticationByWechat(wxAuthDto, request, response);
        } catch (BadCredentialsException e) {
            AuthExceptionDto dto = JacksonUtils.string2Obj(e.getMessage(),AuthExceptionDto.class);;
            return ResponseEntity.build(dto.getCode(),dto.getMessage());
        }
        return loginSuccess(auth);
    }


    /**
     * @方法描述:  各个登录方式成功后操作
     * @参数:
     * @返回值:
     * @创建人: I am God
     * @创建时间:: 2021/2/26
     */
    public ResponseEntity loginSuccess(Authentication auth) throws Exception{
        if (null == auth) {
            return ResponseEntity.build(ResultCode.PARAM_ERROR);
        }
        Member member = (Member) auth.getDetails();
        String token ;
        String key = Global.TOKEN_KEY_HEAD +  member.getUid()+ Global.TOKEN_SPLIT + member.getMobilePhone();
        //获取同账号的上一个token,用于验证同账号只可在线一个设备
        if(redisUtil.hasKey(key)){
            String oldToken = redisUtil.get(key).toString();
            redisUtil.set(Global.OLD_TOKEN + oldToken,oldToken ,securityProperties.getTokenValidityInSeconds() / 1000);
        }
        //生成token 与 保存数据
        token = Global.TOKEN_HEAD + jwtTokenUtils.createToken(member);
        redisUtil.set(token, JacksonUtils.obj2String(member), securityProperties.getTokenValidityInSeconds() / 1000);
        redisUtil.set(key, token, securityProperties.getTokenValidityInSeconds() / 1000);
        //将entity转为vo
        MemberVo memberVo = JacksonUtils.obj2pojo(member,MemberVo.class);
        ClientLoginVo clientLoginVo = new ClientLoginVo();
        clientLoginVo.setMemberVo(memberVo);
        clientLoginVo.setToken(redisUtil.get(key).toString());
        return ResponseEntity.buildSuccess(clientLoginVo);
    }



   /**
    * @方法描述:  授权后获取用户的openid以及unionid
    * @参数:
    * @返回值:
    * @创建人: I am God
    * @创建时间:: 2021/2/24
    */
//    public ResponseEntity getOpenidAndUnionid(String encryptedData,String code,String iv)throws Exception{
//        String param ="?grant_type="+ grantType+"&js_code="+code+"&appid="+appid+"&secret="+secret;
//        String responseString = HttpUtils.sendGet(url, param);
//        Map<String,Object> map = JacksonUtils.string2Obj(responseString,Map.class);
//        logger.info("获取unionid响应:{}", responseString);
//        if (StringUtils.isEmpty(responseString)){
//            return ResponseEntity.build(ResultCode.SEND_REQUEST_ERROR);
//        }
//        if (StringUtils.isNotEmpty(map.get("errcode").toString())){
//            return ResponseEntity.build(ResultCode.GET_UNION_ID_ERROR);
//        }
//        String sessionkey = map.get("session_key").toString();
//
//        String newEncryptedData = encryptedData.replaceAll(" ", "+");
//        String newIv = iv.replace(" ", "+");
//        Map<String,Object> mapResult = JacksonUtils.string2Obj(decryptionUserInfo(newEncryptedData,sessionkey,newIv),Map.class);
//        String openid = (String) mapResult.get("openid");
//        String unionid = (String) mapResult.get("unionid");
//        AppletVo appletVo = new AppletVo();
//        appletVo.setOpenid(openid);
//        appletVo.setUnionid(unionid);
//        return ResponseEntity.buildSuccess(null);
//    }

    /**
     * 小程序解密用户数据
     *
     * @param encryptedData
     * @param sessionKey
     * @param iv
     * @return
     */
//    private String decryptionUserInfo(String encryptedData, String sessionKey, String iv) throws Exception {
//        // 被加密的数据
//        byte[] dataByte = Base64.decode(encryptedData);
//        // 加密秘钥
//        byte[] keyByte = Base64.decode(sessionKey);
//        // 偏移量
//        byte[] ivByte = Base64.decode(iv);
//
//        // 如果密钥不足16位，那么就补足. 这个if 中的内容很重要
//        int base = 16;
//        if (keyByte.length % base != 0) {
//            int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
//            byte[] temp = new byte[groups * base];
//            Arrays.fill(temp, (byte) 0);
//            System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
//            keyByte = temp;
//        }
//        // 初始化
//        String result = "";
//        Security.addProvider(new BouncyCastleProvider());
//        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
//        SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
//        AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
//        parameters.init(new IvParameterSpec(ivByte));
//        cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
//        byte[] resultByte = cipher.doFinal(dataByte);
//        if (null != resultByte && resultByte.length > 0) {
//            result = new String(resultByte, "UTF-8");
//        }
//        return result;
//    }


    /**
     * @方法描述:
     * @参数: 用户登出
     * @返回值:
     * @创建人: I am God
     * @创建时间:: 2021/2/23
     */
    public ResponseEntity logout(String token, HttpServletRequest request) throws Exception {
        Member member = SecurityUtils.getCurrentUser();
        //清除用户的基本信息
        redisUtil.del(token);
        //清除用户的token
        String key = Global.TOKEN_KEY_HEAD +  member.getUid()+ Global.TOKEN_SPLIT + member.getMobilePhone();
        redisUtil.del(key);
        return ResponseEntity.buildSuccess();
    }
}
